package bootstrap

import (
	"github.com/gin-gonic/gin"
	"github.com/kataras/iris/v12/sessions"
	"soccerStar/services"
	"soccerStar/web/controllers"
	"time"
)

type Configurator func(*Bootstrapper)

type Bootstrapper struct {
	*gin.Engine
	AppName      string
	AppOwner     string
	AppSpawnDate time.Time

	Sessions *sessions.Sessions
}

// New returns a new Bootstrapper.
func New(appName, appOwner string, cfgs ...Configurator) *Bootstrapper {
	b := &Bootstrapper{
		AppName:      appName,
		AppOwner:     appOwner,
		AppSpawnDate: time.Now(),
		Engine:       gin.Default(),
	}

	for _, cfg := range cfgs {
		cfg(b)
	}

	return b
}

// SetupViews loads the templates.
func (b *Bootstrapper) SetupViews(viewsDir string) {
	/*	htmlEngine := iris.HTML(viewsDir, ".html").Layout("shared/adminLayout.html")
		// 每次重新加载模版（线上关闭它）
		htmlEngine.Reload(true)
		// 给模版内置各种定制的方法
		htmlEngine.AddFunc("FromUnixtimeShort", func(t int) string {
			dt := time.Unix(int64(t), int64(0))
			return dt.Format(conf.SysTimeformShort)
		})
		htmlEngine.AddFunc("FromUnixtime", func(t int) string {
			dt := time.Unix(int64(t), int64(0))
			return dt.Format(conf.SysTimeform)
		})
		b.RegisterView(htmlEngine)*/
	b.LoadHTMLGlob(viewsDir)
}

// SetupErrorHandlers prepares the http error handlers
// `(context.StatusCodeNotSuccessful`,  which defaults to < 200 || >= 400 but you can change it).
func (b *Bootstrapper) SetupErrorHandlers() {
	/*
		b.OnAnyErrorCode(func(ctx iris.Context) {
			err := iris.Map{
				"app":     b.AppName,
				"status":  ctx.GetStatusCode(),
				"message": ctx.Values().GetString("message"),
			}

			if jsonOutput := ctx.URLParamExists("json"); jsonOutput {
				ctx.JSON(err)
				return
			}

			ctx.ViewData("Err", err)
			ctx.ViewData("Title", "Error")
			ctx.View("shared/sharedError.html")
		})
	*/
}

const (
	// StaticAssets is the root directory for public assets like images, css, js.
	StaticAssets = "./public/"
	// Favicon is the relative 9to the "StaticAssets") favicon path for our app.
	Favicon = "favicon.ico"
)

// Configure accepts configurations and runs them inside the Bootstraper's context.
func (b *Bootstrapper) Configure(cs ...Configurator) {
	for _, c := range cs {
		c(b)
	}
}

// Bootstrap prepares our application.
//
// Returns itself.
func (b *Bootstrapper) Bootstrap() *Bootstrapper {
	b.SetupViews("views/**/*")
	//b.SetupErrorHandlers()

	// static files
	//b.Favicon(StaticAssets + Favicon)

	b.Static(StaticAssets[1:len(StaticAssets)-1], StaticAssets)
	//b.HandleDir(StaticAssets[1:len(StaticAssets)-1], StaticAssets)

	// middleware, after static files
	/*	b.Use(recover.New())
		b.Use(logger.New())*/

	/*	superstarService := services.NewSuperstarService()

		index := mvc.New(b.Party("/"))
		index.Register(superstarService)
		index.Handle(new(controllers.IndexController))

		admin := mvc.New(b.Party("/admin"))
		admin.Router.Use(middleware.BasicAuth)
		admin.Register(superstarService)
		admin.Handle(new(controllers.AdminController))*/
	startService := services.NewSuperstarService()
	indexCon := &controllers.IndexController{
		Service: startService,
	}
	adminCon := &controllers.AdminController{
		Service: startService,
	}
	b.Handle("GET", "/", indexCon.Get)
	b.Handle("GET", "/by", indexCon.GetBy)
	b.Handle("GET", "/search", indexCon.GetSearch)

	b.Handle("GET", "/admin", adminCon.Get)
	b.Handle("GET", "/admin/delete", adminCon.GetDelete)
	b.Handle("GET", "/admin/edit", adminCon.GetEdit)
	b.Handle("POST", "/admin/save", adminCon.PostSave)
	return b
}

// Listen starts the http server with the specified "addr".
func (b *Bootstrapper) Listen(addr string) {
	b.Run(addr)
}
